#include <fstream>
#include <sstream>
#include <string>
#include "../Utilities/utilities.h"
#include "cSceneManager.h"
#include "cResourceManager.h"
using namespace std;

cSceneManager* cSceneManager::s_Instance = 0;
cSceneManager* cSceneManager::GetInstance()
{
	if(!s_Instance)
	{
		s_Instance =  new cSceneManager();
	}
	return s_Instance;
}

void cSceneManager::DestroyInstance()
{
	SAFE_DEL(s_Instance);
}

void cSceneManager::ReadSceneFile()
{
ifstream iFile("SceneManager.txt");
	if (!iFile)
	{
		printf("Cannot open file %s\n",  "SceneManager.txt");
		return;
	}

	istringstream buffer;
	char* s = new char[MAX_LENGTH];

	Obj* o = new Obj();
	string temp;
	float input1, input2, input3;

	while(!iFile.eof())
	{
		
		buffer.clear();
		
		iFile.getline(s, MAX_LENGTH);

		//if s[0] not in [A..Z] -> stop process & go to next line
		if (s[0] < 65 || s[0] > 90) continue;

		buffer.str(s);
		buffer>>temp>>input1>>input2>>input3;
		
		if(temp == "ID") 
			o->obj_Id = (int)input1;
		if(temp == "MODEL") 
			o->model_Id = (int)input1;
		if(temp == "SHADER") 
			o->shader_Id = (int)input1;
		if(temp == "TEXTURE") 
		{
			o->list_Texture_Id.push_back((int)input1);
		}
		if(temp == "POS") 
			o->vPos.Set(input1, input2, input3);
		if(temp == "ROT") 
			o->vRot.Set(input1, input2, input3);
		if(temp == "SCALE") 
		{
			o->vScale.Set(input1, input2, input3);
			list_Object.push_back(o);
			o = new Obj();
		
		}
			
	}

	Matrix ModelObject;
	vector<char*> list_urlTexure;
	//Allocate Object array
	Object = new cObject[(int)list_Object.size()];

	for(int i=0; i < (int)list_Object.size(); i++)
	{
		//Set matrix model and translate - rotate - scale that model
		ModelObject.SetIdentity();

		//Get resources's url
		char* url_Model = cResourceManager::GetInstance()->getUrl_Model(list_Object[i]->model_Id);
		char* url_vShader = cResourceManager::GetInstance()->getUrl_vShader(list_Object[i]->shader_Id);
		char* url_fShader = cResourceManager::GetInstance()->getUrl_fShader(list_Object[i]->shader_Id);
		
		for(int j=0; j < (int)list_Object[i]->list_Texture_Id.size(); j++)
		{
			list_urlTexure.push_back(cResourceManager::GetInstance()->getUrl_Texture(list_Object[i]->list_Texture_Id[j]));
		}

		if(list_Object[i]->obj_Id != 0) //This object is not sky cube
		{
			Matrix ma_Translation;
			Matrix ma_Scale;
			Matrix ma_RotateX, ma_RotateY, ma_RotateZ;	

			ma_Translation.SetTranslation(list_Object[i]->vPos);
			ma_Scale.SetScale(list_Object[i]->vScale);
			ma_RotateX.SetRotationX(list_Object[i]->vRot.x);
			ma_RotateY.SetRotationY(list_Object[i]->vRot.y);
			ma_RotateZ.SetRotationZ(list_Object[i]->vRot.z);

			ModelObject = ma_RotateZ * ma_RotateX * ma_RotateY * ma_Scale * ma_Translation;
		}

		//Set informations to object
		Object[i].SetObject(list_Object[i]->obj_Id, url_Model, url_vShader, url_fShader, list_urlTexure, ModelObject);
		
		//deallocate each object in list_urlTexure then clear list_urlTexure
		for (vector<char*>::iterator iter = list_urlTexure.begin(); iter != list_urlTexure.end(); ++iter)
			SAFE_DEL((*iter));
		list_urlTexure.clear();

		SAFE_DEL_ARRAY(url_Model);
		SAFE_DEL_ARRAY(url_vShader);
		SAFE_DEL_ARRAY(url_fShader);
	}
	
	
	SAFE_DEL(o);
	SAFE_DEL_ARRAY(s);
	

	iFile.close();}

void cSceneManager::DrawAllObjects()
{
	for (int i=0 ; i<(int)list_Object.size() ; i++)
	{
		Object[i].Draw();
	}
}

